package ws.jdbc.concurrent.driver.sqlserver;

import java.sql.SQLException;
import java.util.concurrent.locks.ReentrantLock;
import ws.jdbc.concurrent.driver.sqlserver.tds.ITDSResultSet;
import ws.jdbc.concurrent.driver.sqlserver.tds.TDSMessage;
import static ws.jdbc.concurrent.driver.sqlserver.tds.rpc.StoredProcedures.*;

/**
 * This class provides common functionality for result set cursors.
 * 
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public abstract class ResultSetCursor extends CResultSet {

  public ResultSetCursor(final TDSMessage message, final CResultSet crs, final ReentrantLock lock) throws SQLException {
    super(message, crs.getStatement(), crs.lastRow);
    this.tdsResultSet = crs.getTDSResultSet();
    this.lock = lock;
  }

  @Override
  public void refreshRow() throws SQLException {
    lock.lock();
    try {
      ITDSResultSet tmprs = message.cursorFetch(tdsResultSet.getCursor(), SP_CURSORFETCH_FETCHTYPE_ABSOLUTE, currentRow, 1);
      tdsResultSet.updateRow(rsIndex, tmprs.getRow(0));
    } finally {
      lock.unlock();
    }
  }

  /**
   * Lock the cursor for exclusive access.
   *
   * @throws SQLException if lock is already held by the current thread.
   */
  public void lock() throws SQLException {
    if (!lock.isHeldByCurrentThread()) {
      lock.lock();
    } else {
      throw new SQLException(Messages.msg_already_locked);
    }
  }

  /**
   * Unlock the cursor exclusive access.
   *
   * @throws SQLException if the lock is not held by the current thread.
   */
  public void unlock() throws SQLException {
    try {
      lock.unlock();
    } catch (IllegalMonitorStateException ex) {
      throw new SQLException(Messages.msg_lock_not_held);
    }
  }
}
